public class BST<Key extends Comparable<Key>, Value> {
    private Node root;

    /**
     *  内部类 节点
     */
    private class Node {
        private Key key;
        private Value val;
        private Node left, right;
        private int N;

        public Node(Key key, Value val, int N) {
            this.key = key;
            this.val = val;
            this.N = N;
        }
    }

    /**
     *  返回树的元素数量
     * @return
     */
    public int size() {
        return size(root);
    }

    private int size(Node x) {
        if(x == null) {
            return 0;
        } else {
            return x.N;
        }
    }

    /**
     *  获取
     * @param key 获取的键
     * @return  返回对应的值
     */
    public Value get(Key key) {
        return get(root, key);
    }

    private Value get(Node x, Key key) {
        // 在以x为根节点的子树中查找并返回key对应的值
        // 如果找不到则返回null
        if(x == null) {
            return null;
        }
        int cmp = key.compareTo(x.key);
        if(cmp < 0) {
            return get(x.left, key);
        } else if(cmp > 0) {
            return get(x.right, key);
        } else {
            return x.val;
        }
    }

    /**
     *  添加
     * @param key 添加的键
     * @param val 添加的值
     */
    public void put(Key key, Value val) {
        // 查找key，找到则更新它的值，否则为它创建一个新的节点
        root = put(root, key, val);
    }

    private Node put(Node x, Key key, Value val) {
        // 如果key存在于以x为根节点的子树中则更新它的值
        // 否则将以key和val为键值对的新节点插入该子树中
        if(x == null) {
            return new Node(key, val, 1);
        }
        int cmp = key.compareTo(x.key);
        if(cmp < 0) {
            x.left = put(x.left, key, val);
        } else if(cmp > 0) {
            x.right = put(x.right, key, val);
        } else {
            x.val = val;
        }
        x.N = size(x.left) + size(x.right) + 1;
        return x;
    }

    /**
     *  求最小键
     * @return  返回键
     */
    public Key min() {
        return min(root).key;
    }

    private Node min(Node x) {
        if(x.left == null) {
            return x;
        }
        return min(x.left);
    }

    public Key floor(Key key) {
        Node x = floor(root, key);
        if(x == null) {
            return null;
        }
        return x.key;
    }
    private Node floor(Node x, Key key) {
        if(x == null) {
            return null;
        }
        int cmp = key.compareTo(x.key);
        if(cmp == 0) {
            return x;
        }
        if(cmp < 0) {
            return floor(x.left, key);
        }
        Node t = floor(x.right, key);
        if(t != null) {
            return t;
        } else {
            return x;
        }
    }

}